/**
 * @p.md
 * 
 * Grain抽象
 * 提供集群化Actor的高级接口
 */
import { ActorSystem, Props } from '../actor';
import { PID } from '../actor/pid';
import { Cluster } from './cluster';
import { ClusterIdentity } from './clusterIdentity';

/**
 * Grain接口
 * 定义了集群化Actor的基础方法
 */
export interface Grain {
  /**
   * 获取Grain的ID
   */
  getIdentity(): string;
  
  /**
   * 获取Grain的类型
   */
  getKind(): string;
  
  /**
   * 获取Grain的PID
   */
  getPID(): PID | null;
  
  /**
   * 关闭Grain
   */
  shutdown(): Promise<void>;
}

/**
 * GrainFactory接口
 * 定义了Grain的创建方法
 */
export interface GrainFactory<T extends Grain> {
  /**
   * 创建特定类型的Grain
   * @param identity 身份标识
   */
  get(identity: string): T;
}

/**
 * 基础Grain抽象类
 * 实现了Grain接口的通用功能
 */
export abstract class GrainBase implements Grain {
  /**
   * Grain Actor的PID
   */
  protected pid: PID | null = null;
  
  /**
   * 构造函数
   * @param cluster 集群引用
   * @param kind Grain类型
   * @param identity 身份标识
   */
  constructor(
    protected cluster: Cluster,
    protected kind: string,
    protected identity: string
  ) {}
  
  /**
   * 获取Grain的身份标识
   */
  getIdentity(): string {
    return this.identity;
  }
  
  /**
   * 获取Grain的类型
   */
  getKind(): string {
    return this.kind;
  }
  
  /**
   * 获取Grain的PID
   */
  getPID(): PID | null {
    return this.pid;
  }
  
  /**
   * 关闭Grain
   */
  async shutdown(): Promise<void> {
    if (this.pid) {
      const actorSystem = this.cluster.getActorSystem();
      await actorSystem.root.stop(this.pid);
      this.pid = null;
    }
  }
  
  /**
   * 激活Grain
   * 在集群中查找或创建Grain Actor
   * @param timeout 超时时间(毫秒)
   */
  protected async activate(timeout?: number): Promise<PID | null> {
    if (this.pid) {
      return this.pid;
    }
    
    try {
      this.pid = await this.cluster.getAsync(this.kind, this.identity, timeout);
      return this.pid;
    } catch (error) {
      console.error(`激活Grain失败: ${(error as Error).message}`);
      return null;
    }
  }
}

/**
 * Grain注册表类
 * 管理Grain的注册和查找
 */
export class GrainRegistry {
  /**
   * Grain类型到Actor创建Props的映射
   */
  private grainPropsMap: Map<string, (identity: string) => Props> = new Map();
  
  /**
   * 单例实例
   */
  private static instance: GrainRegistry | null = null;
  
  /**
   * 私有构造函数
   */
  private constructor() {}
  
  /**
   * 获取单例实例
   */
  static getInstance(): GrainRegistry {
    if (!GrainRegistry.instance) {
      GrainRegistry.instance = new GrainRegistry();
    }
    return GrainRegistry.instance;
  }
  
  /**
   * 注册Grain类型
   * @param kind Grain类型
   * @param propsFactory Props工厂函数
   */
  registerGrain(kind: string, propsFactory: (identity: string) => Props): void {
    this.grainPropsMap.set(kind, propsFactory);
  }
  
  /**
   * 获取Grain的Props
   * @param kind Grain类型
   * @param identity 身份标识
   */
  getGrainProps(kind: string, identity: string): Props | null {
    const factory = this.grainPropsMap.get(kind);
    if (!factory) {
      return null;
    }
    
    return factory(identity);
  }
  
  /**
   * 检查Grain类型是否已注册
   * @param kind Grain类型
   */
  hasGrain(kind: string): boolean {
    return this.grainPropsMap.has(kind);
  }
  
  /**
   * 获取所有已注册的Grain类型
   */
  getRegisteredGrainKinds(): string[] {
    return Array.from(this.grainPropsMap.keys());
  }
}

/**
 * Grain活动器Actor
 * 负责在集群节点上创建Grain Actor
 */
export class GrainActivatorActor {
  /**
   * 构造函数
   * @param actorSystem Actor系统引用
   */
  constructor(private actorSystem: ActorSystem) {}
  
  /**
   * 消息处理
   */
  async receive(context: any): Promise<void> {
    const message = context.message;
    
    // 处理激活请求
    if (this.isActivationRequest(message)) {
      await this.handleActivation(context, message);
    }
  }
  
  /**
   * 处理激活请求
   */
  private async handleActivation(context: any, request: any): Promise<void> {
    try {
      const { clusterIdentity, requestId } = request;
      const identity = new ClusterIdentity(clusterIdentity.kind, clusterIdentity.identity);
      
      // 获取Grain注册表
      const registry = GrainRegistry.getInstance();
      
      // 检查Grain类型是否已注册
      if (!registry.hasGrain(identity.kind)) {
        await context.respond({
          clusterIdentity,
          requestId,
          success: false,
          error: `未注册的Grain类型: ${identity.kind}`
        });
        return;
      }
      
      // 获取Props并创建Actor
      const props = registry.getGrainProps(identity.kind, identity.identity);
      if (!props) {
        await context.respond({
          clusterIdentity,
          requestId,
          success: false,
          error: `无法创建Grain Props: ${identity.kind}/${identity.identity}`
        });
        return;
      }
      
      // 使用唯一ID创建Actor
      const actorId = `${identity.kind}-${identity.identity}`;
      const pid = this.actorSystem.root.spawnNamed(props, actorId);
      
      // 返回成功响应
      await context.respond({
        clusterIdentity,
        requestId,
        pidId: pid.id,
        pidAddress: pid.address,
        success: true
      });
    } catch (error) {
      await context.respond({
        clusterIdentity: request.clusterIdentity,
        requestId: request.requestId,
        success: false,
        error: `激活失败: ${(error as Error).message}`
      });
    }
  }
  
  /**
   * 类型保护函数
   */
  private isActivationRequest(message: any): boolean {
    return message && 
           typeof message === 'object' && 
           'clusterIdentity' in message && 
           'requestId' in message;
  }
} 